//
// Created by 陈成 on 2019/9/19.
//

#include "InstJ.h"

InstJ::InstJ(uint32_t pc, sc_bv<32> value, RegBank<REG_NUM> *r, RegBank<CSR_NUM> *csr, Mem *m) :
        Inst(pc, value, r, csr, m),
        imm   ((value.range(31, 31),
                value.range(19, 12),
                value.range(20, 20),
                value.range(30, 21),
                sc_bv<1>(0))),
        rd    (value.range(11,  7)),
        opcode(value.range( 6,  0)){

}

uint32_t
InstJ::exec() {
    uint32_t u32_rd = rd.to_uint();
    int32_t  i32_imm = extendImm(imm).to_int();

    uint32_t pc_nxt = pc + 4;
    switch (opcode.to_uint()) {
    case 0b0010111: // JAL
        pc_nxt = pc + i32_imm;
        r->write(u32_rd, pc + 4);

        LOG("JAL RD: %d, IMM: %d", rd.to_uint(), imm.to_uint());
        LOG("Jump to: %d + %d", pc, i32_imm);
        break;
    default:
        assert(false);
        break;
    }

    return pc_nxt;
}
